home *** CD-ROM | disk | FTP | other *** search
/ Mac Power 1997 December / MACPOWER-1997-12.ISO.7z / MACPOWER-1997-12.ISO / AMUG / PROGRAMMING / Raven 1.2 Examples.sit / Raven 1.2 Examples / Quill / Source / ResourceMap.cpp < prev    next >
C/C++ Source or Header  |  1997-09-03  |  12KB  |  500 lines

  1. /*
  2.  *  File:       ResourceMap.cpp
  3.  *  Summary:       A class that knows how to manage resources of a specified type. The
  4.  *                resource data is kept in memory so this class is unsuitable for large
  5.  *                resources. 
  6.  *  Written by: Jesse Jones
  7.  *
  8.  *  Copyright ゥ 1996 Jesse Jones. Permission to use, copy, modify, and distribute this
  9.  *    file as source or object code is hereby granted without fee. Permission to sell the
  10.  *    source code is granted only to non-profit institutions. This file is provided "as is" 
  11.  *    without express or implied warranty. 
  12.  *
  13.  *  Change History (most recent first):    
  14.  *
  15.  *         <->     8/15/96    JDJ        Created
  16.  */
  17.  
  18. #include "ResourceMap.h"
  19.  
  20. #include <Map.h>
  21. #include <Resources.h>
  22.  
  23. #include <ZCommand.h>
  24. #include <ZDragSession.h>
  25. #include <ZExceptions.h>
  26. #include <ZHandleStream.h>
  27. #include <ZLocker.h>
  28. #include <ZResUtils.h>
  29. #include <ZStream.h>
  30. #include <ZStringUtils.h>
  31.  
  32.  
  33. // ===================================================================================
  34. //    struct SResourceMapMessage
  35. // ===================================================================================
  36.  
  37. //---------------------------------------------------------------
  38. //
  39. // SResourceMapMessage::SResourceMapMessage
  40. //
  41. //---------------------------------------------------------------
  42. SResourceMapMessage::SResourceMapMessage(CResourceMap* rMap, ResID id, long mesg)
  43. {
  44.     ASSERT(rMap != nil);
  45.     
  46.     rsrcMap = rMap;
  47.     
  48.     if (mesg != kDeletingResources)
  49.         oldRsrc = newRsrc = rsrcMap->GetResource(id);
  50.     
  51.     message = mesg;
  52. }
  53.  
  54. #pragma mark -
  55.  
  56. //---------------------------------------------------------------
  57. //
  58. // SResource::SResource
  59. //
  60. //---------------------------------------------------------------
  61. SResource::SResource(const TDragSession& session, ItemReference item, FlavorType flavor)
  62. {
  63.     THandle data = session.GetData(item, flavor);
  64.     TInHandleStream stream(data);                
  65.         stream >> *this;
  66. }
  67.  
  68.  
  69. //---------------------------------------------------------------
  70. //
  71. // operator>> (SResource)
  72. //
  73. //---------------------------------------------------------------
  74. TInStream& operator>>(TInStream& stream, SResource& value)
  75. {
  76.     Handle hand = value.data;
  77.     
  78.     stream >> value.id >> value.name >> hand;
  79.  
  80.     return stream;
  81. }
  82.  
  83.  
  84. //---------------------------------------------------------------
  85. //
  86. // operator<< (SResource)
  87. //
  88. //---------------------------------------------------------------
  89. TOutStream& operator<<(TOutStream& stream, const SResource& value)
  90. {
  91.     stream << value.id << value.name << value.data;
  92.  
  93.     return stream;
  94. }
  95.  
  96.  
  97. //---------------------------------------------------------------
  98. //
  99. // SResource::AddData
  100. //
  101. //---------------------------------------------------------------
  102. void SResource::AddData(TDragSession& session, ItemReference item, FlavorType flavor, FlavorFlags flags) const
  103. {
  104.     THandle bits;
  105.  
  106.     {
  107.     TOutHandleStream stream(bits);                
  108.         stream << *this;
  109.     }
  110.  
  111.     {
  112.     TLocker lock(bits);
  113.         session.AddData(item, flavor, bits.GetPtr(), bits.GetSize(), flags);
  114.     }
  115. }
  116.  
  117. #pragma mark -
  118.  
  119. // ===================================================================================
  120. //    class CResourceMap
  121. // ===================================================================================
  122.  
  123. //---------------------------------------------------------------
  124. //
  125. // CResourceMap::~CResourceMap
  126. //
  127. //---------------------------------------------------------------
  128. CResourceMap::~CResourceMap()
  129. {
  130.     delete mResources;
  131. }
  132.  
  133.  
  134. //---------------------------------------------------------------
  135. //
  136. // CResourceMap::CResourceMap
  137. //
  138. //---------------------------------------------------------------
  139. CResourceMap::CResourceMap(ResType type)
  140. {
  141.     ASSERT(type != '????');
  142.     
  143.     mType = type;
  144.     mResources = new ResourceMap;
  145. }
  146.  
  147.  
  148. //---------------------------------------------------------------
  149. //
  150. // CResourceMap::ReadResources
  151. //
  152. //---------------------------------------------------------------
  153. void CResourceMap::ReadResources()
  154. {
  155.     // Zap any old resources that may be hanging around
  156.     if (mResources->size() > 0)
  157.         this->Broadcast(SResourceMapMessage(this, 0, kDeletingResources));
  158.     mResources->erase(mResources->begin(), mResources->end());
  159.     
  160.     // Resource zapping may cause resource windows to be closed.
  161.     // To ensure that this doesn't overwrite the data we're about
  162.     // to read we'll execute pending deferred deletes here.
  163.     TCommand::ExecuteCommands(false);
  164.  
  165.     // and read in the new resources.
  166.     short numViews = ::Count1Resources(mType);
  167.     for (short index = 1; index <= numViews; index++) {
  168.         Handle hand = ::Get1IndResource(mType, index);
  169.         ThrowIfResFail(hand);
  170.         
  171.         ResID   id;
  172.         ResType type;
  173.         Str255  name;
  174.         ::GetResInfo(hand, &id, &type, name);
  175.         ThrowIfResError();
  176.  
  177.         this->AddResource(SResource(id, PStrToStr(name), hand));
  178.     }
  179. }
  180.  
  181.  
  182. //---------------------------------------------------------------
  183. //
  184. // CResourceMap::WriteResources
  185. //
  186. // ・・・ハrewrite this so that an error while writing the new data
  187. // ・・・ハout doesn't trash all of the old data
  188. //
  189. //---------------------------------------------------------------
  190. void CResourceMap::WriteResources()
  191. {
  192.     // Out with the old...
  193.     Delete1Resource(mType);
  194.  
  195.     // and in with the new.
  196.     ResourceMap::iterator iter = mResources->begin();
  197.     while (iter != mResources->end()) {
  198.         ResourceEntry& entry = *iter++;
  199.         ResID id = entry.first;
  200.         SResourceData& data = entry.second;
  201.  
  202.         long size = data.hand.GetSize();
  203.         
  204.         Handle rsrc = ::NewHandle(size);
  205.         ThrowIfMemFail(rsrc);
  206.         
  207.         ::BlockMoveData(data.hand.GetUnsafePtr(), *rsrc, size);
  208.         ::AddResource(rsrc, mType, id, StrToPStr(data.name));
  209.         ThrowIfResError();
  210.  
  211.         ::ReleaseResource(rsrc);
  212.         
  213.         data.dirty = false;
  214.         this->Broadcast(SResourceMapMessage(this, id, kSavedResource));
  215.     }    
  216. }
  217.  
  218.  
  219. //---------------------------------------------------------------
  220. //
  221. // CResourceMap::GetNumResources
  222. //
  223. //---------------------------------------------------------------
  224. long CResourceMap::GetNumResources() const
  225. {
  226.     return mResources->size();
  227. }
  228.  
  229.  
  230. //---------------------------------------------------------------
  231. //
  232. // CResourceMap::GetLastResourceID
  233. //
  234. //---------------------------------------------------------------
  235. ResID CResourceMap::GetLastResourceID() const
  236. {
  237.     ResID lastID = 255;
  238.     
  239.     if (mResources->size() > 0) {
  240.         ResourceMap::reverse_iterator iter = mResources->rbegin();
  241.     
  242.         const ResourceEntry& entry = *iter++;
  243.         lastID = entry.first;
  244.     }    
  245.  
  246.     return lastID;
  247. }
  248.  
  249.  
  250. //---------------------------------------------------------------
  251. //
  252. // CResourceMap::GetResourceName
  253. //
  254. //---------------------------------------------------------------
  255. string CResourceMap::GetResourceName(ResID id) const
  256. {
  257.     ASSERT(mResources->count(id) == 1);
  258.  
  259.     const SResourceData& data = mResources->operator[](id);
  260.     
  261.     return data.name;
  262. }
  263.  
  264.  
  265. //---------------------------------------------------------------
  266. //
  267. // CResourceMap::GetResourceData
  268. //
  269. //---------------------------------------------------------------
  270. THandle CResourceMap::GetResourceData(ResID id) const
  271. {
  272.     ASSERT(mResources->count(id) == 1);
  273.  
  274.     const SResourceData& data = mResources->operator[](id);
  275.     
  276.     return data.hand;
  277. }
  278.  
  279.  
  280. //---------------------------------------------------------------
  281. //
  282. // CResourceMap::GetResource
  283. //
  284. //---------------------------------------------------------------
  285. SResource CResourceMap::GetResource(ResID id) const
  286. {
  287.     ASSERT(mResources->count(id) == 1);
  288.  
  289.     const SResourceData& data = mResources->operator[](id);
  290.     
  291.     return SResource(id, data.name, data.hand);
  292. }
  293.  
  294.  
  295. //---------------------------------------------------------------
  296. //
  297. // CResourceMap::IsDirty ()
  298. //
  299. //---------------------------------------------------------------
  300. bool CResourceMap::IsDirty() const
  301. {
  302.     bool dirty = false;
  303.     
  304.     ResourceMap::const_iterator iter = mResources->begin();
  305.     while (!(iter == mResources->end()) && !dirty) {        // CW Pro 1 has problems finding operator!= when precompiling SGI STL
  306.         const ResourceEntry& entry = *iter++;
  307.         const SResourceData& data = entry.second;
  308.         
  309.         dirty = data.dirty;
  310.     }    
  311.     
  312.     return dirty;
  313. }
  314.  
  315.  
  316. //---------------------------------------------------------------
  317. //
  318. // CResourceMap::IsDirty (ResID)
  319. //
  320. //---------------------------------------------------------------
  321. bool CResourceMap::IsDirty(ResID id) const
  322. {
  323.     ASSERT(mResources->count(id) == 1);
  324.  
  325.     const SResourceData& data = mResources->operator[](id);
  326.     
  327.     return data.dirty;
  328. }
  329.  
  330.  
  331. //---------------------------------------------------------------
  332. //
  333. // CResourceMap::ClearDirty ()
  334. //
  335. //---------------------------------------------------------------
  336. void CResourceMap::ClearDirty()
  337. {
  338.     ResourceMap::iterator iter = mResources->begin();
  339.     while (iter != mResources->end()) {
  340.         ResourceEntry& entry = *iter++;
  341.         SResourceData& data = entry.second;
  342.         
  343.         data.dirty = false;
  344.     }    
  345. }
  346.  
  347.  
  348. //---------------------------------------------------------------
  349. //
  350. // CResourceMap::ClearDirty (ResID)
  351. //
  352. //---------------------------------------------------------------
  353. void CResourceMap::ClearDirty(ResID id)
  354. {
  355.     ASSERT(mResources->count(id) == 1);
  356.  
  357.     SResourceData& data = mResources->operator[](id);
  358.     
  359.     data.dirty = false;
  360. }
  361.  
  362.  
  363. //---------------------------------------------------------------
  364. //
  365. // CResourceMap::SetResourceName
  366. //
  367. //---------------------------------------------------------------
  368. void CResourceMap::SetResourceName(ResID id, const string& newName)
  369. {
  370.     ASSERT(mResources->count(id) == 1);
  371.  
  372.     SResourceData& data = mResources->operator[](id);
  373.     if (data.name != newName) {
  374.         SResourceMapMessage mesg(this, id, kSetResourceName);
  375.         
  376.         data.name = newName;
  377.         data.dirty = true;
  378.         
  379.         mesg.newRsrc.name = newName;
  380.         this->Broadcast(mesg);
  381.     }
  382. }
  383.  
  384.  
  385. //---------------------------------------------------------------
  386. //
  387. // CResourceMap::SetResourceData
  388. //
  389. //---------------------------------------------------------------
  390. void CResourceMap::SetResourceData(ResID id, const THandle& newHand)
  391. {
  392.     ASSERT(mResources->count(id) == 1);
  393.  
  394.     SResourceData& data = mResources->operator[](id);
  395.  
  396.     if (newHand != data.hand) {
  397.     
  398.         // Do this the hard way to avoid invalidating objects that have
  399.         // a copy of data.hand    
  400.         long bytes = newHand.GetSize();
  401.         data.hand.SetSize(bytes);
  402.         BlockMoveData(newHand.GetUnsafePtr(), data.hand.GetUnsafePtr(), bytes);
  403.         
  404.         data.dirty = true;
  405.         
  406.         this->Broadcast(SResourceMapMessage(this, id, kSetResourceData));
  407.     }
  408. }
  409.  
  410.  
  411. //---------------------------------------------------------------
  412. //
  413. // CResourceMap::SetResourceID
  414. //
  415. //---------------------------------------------------------------
  416. void CResourceMap::SetResourceID(ResID oldID, ResID newID)
  417. {
  418.     ASSERT(mResources->count(oldID) == 1);
  419.  
  420.     if (oldID != newID) {
  421.         ASSERT(mResources->count(newID) == 0);
  422.  
  423.         SResourceMapMessage mesg(this, oldID, kSetResourceID);
  424.  
  425.         string name  = this->GetResourceName(oldID);
  426.         THandle data = this->GetResourceData(oldID);
  427.  
  428.         mResources->erase(oldID);
  429.         mResources->insert(ResourceEntry(newID, SResourceData(data, name, true)));
  430.         
  431.         mesg.newRsrc.id = newID;
  432.         this->Broadcast(mesg);
  433.     }
  434.     
  435.     ASSERT(mResources->count(newID) == 1);
  436. }
  437.  
  438.  
  439. //---------------------------------------------------------------
  440. //
  441. // CResourceMap::AddResource ()
  442. //
  443. //---------------------------------------------------------------
  444. ResID CResourceMap::AddResource()
  445. {
  446.     ResID id = this->GetLastResourceID() + 1;
  447.     ASSERT(mResources->count(id) == 0);
  448.         
  449.     mResources->insert(ResourceEntry(id, SResourceData(THandle(), "", true)));
  450.     
  451.     this->Broadcast(SResourceMapMessage(this, id, kAddedResource));
  452.     
  453.     return id;
  454. }
  455.  
  456.  
  457. //---------------------------------------------------------------
  458. //
  459. // CResourceMap::AddResource (SResource)
  460. // 
  461. //---------------------------------------------------------------
  462. void CResourceMap::AddResource(const SResource& rsrc)
  463. {
  464.     ASSERT(mResources->count(rsrc.id) == 0);
  465.     
  466.     mResources->insert(ResourceEntry(rsrc.id, SResourceData(rsrc.data, rsrc.name, true)));
  467.  
  468.     this->Broadcast(SResourceMapMessage(this, rsrc.id, kAddedResource));
  469. }
  470.  
  471.  
  472. //---------------------------------------------------------------
  473. //
  474. // CResourceMap::DeleteResource
  475. //
  476. //---------------------------------------------------------------
  477. void CResourceMap::DeleteResource(ResID id)
  478. {
  479.     ASSERT(mResources->count(id) == 1);
  480.  
  481.     SResourceMapMessage mesg(this, id, kDeletedResource);
  482.  
  483.     mResources->erase(id);
  484.     
  485.     this->Broadcast(mesg);
  486. }
  487.  
  488.  
  489. //---------------------------------------------------------------
  490. //
  491. // CResourceMap::HasResource
  492. //
  493. //---------------------------------------------------------------
  494. bool CResourceMap::HasResource(ResID id) const
  495. {
  496.     return mResources->count(id) == 1;
  497. }
  498.  
  499.  
  500.